{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting data/train-images-idx3-ubyte.gz\n",
      "Extracting data/train-labels-idx1-ubyte.gz\n",
      "Extracting data/t10k-images-idx3-ubyte.gz\n",
      "Extracting data/t10k-labels-idx1-ubyte.gz\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.contrib import rnn\n",
    "old_v = tf.compat.v1.logging.get_verbosity()\n",
    "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)\n",
    "# 导入 MINST 数据集\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "mnist = input_data.read_data_sets(\"data/\", one_hot=True)\n",
    "tf.compat.v1.logging.set_verbosity(old_v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = 100\n",
    "time_step =28 # 时间步（每个时间步处理图像的一行）\n",
    "data_length = 28 # 每个时间步输入数据的长度（这里就是图像的宽度）\n",
    "learning_rate = 0.01"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: Logging before flag parsing goes to stderr.\n",
      "W0816 15:02:08.115901 140215968261952 module_wrapper.py:136] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/util/module_wrapper.py:163: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.\n",
      "\n",
      "W0816 15:02:08.121917 140215968261952 deprecation.py:323] From <ipython-input-3-b0516593e217>:14: GRUCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "This class is equivalent as tf.keras.layers.GRUCell, and will be replaced by that in Tensorflow 2.0.\n",
      "W0816 15:02:08.123775 140215968261952 deprecation.py:323] From <ipython-input-3-b0516593e217>:14: MultiRNNCell.__init__ (from tensorflow.python.ops.rnn_cell_impl) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "This class is equivalent as tf.keras.layers.StackedRNNCells, and will be replaced by that in Tensorflow 2.0.\n",
      "W0816 15:02:08.124845 140215968261952 deprecation.py:323] From <ipython-input-3-b0516593e217>:16: dynamic_rnn (from tensorflow.python.ops.rnn) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use `keras.layers.RNN(cell)`, which is equivalent to this API\n",
      "W0816 15:02:08.186853 140215968261952 deprecation.py:323] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/ops/rnn_cell_impl.py:558: Layer.add_variable (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use `layer.add_weight` method instead.\n",
      "W0816 15:02:08.196528 140215968261952 deprecation.py:506] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/ops/rnn_cell_impl.py:564: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
      "W0816 15:02:08.282342 140215968261952 deprecation.py:506] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/ops/rnn_cell_impl.py:574: calling Zeros.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
      "W0816 15:02:08.359511 140215968261952 deprecation.py:323] From <ipython-input-3-b0516593e217>:17: dense (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.Dense instead.\n",
      "W0816 15:02:08.360661 140215968261952 deprecation.py:323] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/layers/core.py:187: Layer.apply (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use `layer.__call__` method instead.\n",
      "W0816 15:02:08.374940 140215968261952 module_wrapper.py:136] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/util/module_wrapper.py:163: The name tf.losses.softmax_cross_entropy is deprecated. Please use tf.compat.v1.losses.softmax_cross_entropy instead.\n",
      "\n",
      "W0816 15:02:08.402209 140215968261952 deprecation.py:323] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/ops/losses/losses_impl.py:121: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.where in 2.0, which has the same broadcast rule as np.where\n",
      "W0816 15:02:08.411217 140215968261952 module_wrapper.py:136] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/util/module_wrapper.py:163: The name tf.train.AdamOptimizer is deprecated. Please use tf.compat.v1.train.AdamOptimizer instead.\n",
      "\n",
      "W0816 15:02:08.920478 140215968261952 module_wrapper.py:136] From /usr/local/python3/lib/python3.6/site-packages/tensorflow_core/python/util/module_wrapper.py:163: The name tf.metrics.accuracy is deprecated. Please use tf.compat.v1.metrics.accuracy instead.\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step: 0 train loss: 2.3052 | val accuracy: 0.13\n",
      "step: 100 train loss: 0.1519 | val accuracy: 0.53\n",
      "step: 200 train loss: 0.1007 | val accuracy: 0.68\n",
      "step: 300 train loss: 0.0438 | val accuracy: 0.75\n",
      "step: 400 train loss: 0.0623 | val accuracy: 0.80\n",
      "step: 500 train loss: 0.1239 | val accuracy: 0.83\n",
      "step: 600 train loss: 0.0623 | val accuracy: 0.85\n",
      "step: 700 train loss: 0.0691 | val accuracy: 0.86\n",
      "step: 800 train loss: 0.0951 | val accuracy: 0.88\n",
      "step: 900 train loss: 0.0745 | val accuracy: 0.89\n",
      "step: 1000 train loss: 0.1131 | val accuracy: 0.89\n",
      "step: 1100 train loss: 0.1958 | val accuracy: 0.90\n",
      "step: 1200 train loss: 0.0453 | val accuracy: 0.91\n",
      "step: 1300 train loss: 0.0631 | val accuracy: 0.91\n",
      "step: 1400 train loss: 0.0495 | val accuracy: 0.92\n",
      "step: 1500 train loss: 0.0844 | val accuracy: 0.92\n",
      "step: 1600 train loss: 0.0420 | val accuracy: 0.92\n",
      "step: 1700 train loss: 0.0085 | val accuracy: 0.93\n",
      "step: 1800 train loss: 0.0670 | val accuracy: 0.93\n",
      "step: 1900 train loss: 0.2119 | val accuracy: 0.93\n",
      "step: 2000 train loss: 0.0291 | val accuracy: 0.93\n",
      "step: 2100 train loss: 0.0566 | val accuracy: 0.94\n",
      "step: 2200 train loss: 0.0220 | val accuracy: 0.94\n",
      "step: 2300 train loss: 0.0533 | val accuracy: 0.94\n",
      "step: 2400 train loss: 0.0464 | val accuracy: 0.94\n",
      "step: 2500 train loss: 0.1071 | val accuracy: 0.94\n",
      "step: 2600 train loss: 0.0377 | val accuracy: 0.94\n",
      "step: 2700 train loss: 0.1267 | val accuracy: 0.94\n",
      "step: 2800 train loss: 0.1242 | val accuracy: 0.94\n",
      "step: 2900 train loss: 0.2198 | val accuracy: 0.94\n",
      "test loss: 0.9424\n"
     ]
    }
   ],
   "source": [
    "# 定义占位符\n",
    "X_ = tf.placeholder(tf.float32, [None, 784])\n",
    "Y_ = tf.placeholder(tf.int32, [None, 10])\n",
    "\n",
    "# dynamic_rnn的输入数据(batch_size, max_time, ...)\n",
    "inputs = tf.reshape(X_, [-1, time_step, data_length])\n",
    "\n",
    "# 验证集\n",
    "validate_data = {X_: mnist.validation.images, Y_: mnist.validation.labels}\n",
    "# 测试集\n",
    "test_data = {X_: mnist.test.images, Y_: mnist.test.labels}\n",
    "\n",
    "# 定义一个两层的GRU模型\n",
    "gru_layers = rnn.MultiRNNCell([rnn.GRUCell(num_units=num) for num in [100, 100]], state_is_tuple=True)\n",
    "\n",
    "outputs, h_ = tf.nn.dynamic_rnn(gru_layers, inputs, dtype=tf.float32)\n",
    "output = tf.layers.dense(outputs[:, -1, :], 10) #获取GRU网络的最后输出状态\n",
    "\n",
    "# 定义交叉熵损失函数和优化器\n",
    "loss = tf.losses.softmax_cross_entropy(onehot_labels=Y_, logits=output)\n",
    "train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)\n",
    "\n",
    "# 计算准确率\n",
    "accuracy = tf.metrics.accuracy(labels=tf.argmax(Y_, axis=1), predictions=tf.argmax(output, axis=1))[1]\n",
    "\n",
    "## 初始化变量\n",
    "sess = tf.Session()\n",
    "init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())\n",
    "sess.run(init)\n",
    "\n",
    "for step in range(3000):\n",
    "    # 获取一个batch的训练数据\n",
    "    train_x, train_y = mnist.train.next_batch(batch_size)\n",
    "    _, loss_ = sess.run([train_op, loss], {X_: train_x, Y_: train_y})\n",
    "    \n",
    "    # 在验证集上计算准确率\n",
    "    if step % 100 == 0:\n",
    "        val_acc = sess.run(accuracy, feed_dict=validate_data)\n",
    "        print('step:', step,'train loss: %.4f' % loss_, '| val accuracy: %.2f' % val_acc)\n",
    "    \n",
    "## 计算测试集史上的准确率\n",
    "test_acc = sess.run(accuracy, feed_dict=test_data)\n",
    "print('test loss: %.4f' % test_acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
